package com.lx.idea.aspect;

import cn.hutool.core.util.RandomUtil;
import com.lx.idea.common.Constant;
import com.lx.idea.common.config.SFtpProperties;
import com.lx.idea.common.util.*;
import com.lx.idea.model.CurrentNode;
import com.lx.idea.report.config.RealTimeReport;
import com.lx.idea.report.model.InstitutionRegisterInfo;
import com.lx.idea.report.model.MethodRuntimeInfo;
import com.lx.idea.report.model.RootRealTimeInfo;
import com.lx.idea.service.ESService;
import com.lx.idea.service.NodeServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.w3c.dom.Document;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author ybb
 * @Description
 * @Date 2021/9/13 17:41
 */
@Aspect
@Slf4j
@Configuration
public class AnalysisAspect {

    @Autowired
    NodeServiceImpl nodeService;

    @Autowired
    ESService esUtil;

    @Autowired
    SFtpProperties sFtpProperties;

    @Value("${es.index}")
    String index;

    @Value("${xmlPath}")
    String xmlPath;
    @Value("${tarPath}")
    String tarPath;
    @Value("${rootPath}")
    String rootPath;
    @Value("${outDir}")
    String outDir;
    @Value("${privateKey}")
    String privateKey;

    static CurrentNode currentNode =null;

    @Pointcut("@annotation(spring.boot.aop.annotation.annotation.LogAnnotation)")
    public void aroundPoint(){}

    @Around("@annotation(LogAnnotation)")
    public Object aroundPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        currentNode = nodeService.getCurrPrefix();
        long startTime,endTime;
        String startDate = null,endDate = null;
        Object obj;
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            startTime = System.currentTimeMillis();
            startDate = sdf.format(startTime);
            obj = joinPoint.proceed(joinPoint.getArgs());
            endTime = System.currentTimeMillis();
            endDate = sdf.format(endTime);

//            System.out.print(Integer.parseInt(null));

            MethodRuntimeInfo runtimeInfo = new MethodRuntimeInfo();
            runtimeInfo.setStartTime(startTime);
            runtimeInfo.setStartTimeStr(startDate);
            runtimeInfo.setEndTime(endTime);
            runtimeInfo.setEndTimeStr(endDate);
            runtimeInfo.setExeTime(endTime-startTime);
            runtimeInfo.setNodeName(currentNode.getNodeName());
            runtimeInfo.setNodePrefix(currentNode.getPrefixSelf());
            runtimeInfo.setNodeLevel(currentNode.getLevel());
            //存储ES
            log.info("开始记录解析日志");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    esUtil.save(index,Constant.MoStatInfo,runtimeInfo);
                }
            }).start();
        } catch (Throwable t) {
            // 当方法中报异常时，会抛出这里的异常，
            log.info("解析异常开始上报");
            RootRealTimeInfo exception = new RootRealTimeInfo();
            exception.setRepStatusType("1");
            exception.setRepEventNo(System.currentTimeMillis()+"");
            exception.setOccurTime(startDate);
            exception.setExcCause(t.getClass().getName()+":"+t.getMessage());
            exception.setExcType("2");
            syncReport(exception,currentNode.getLevel());

            throw t;
        }
        String classAndMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        log.info("执行 " + classAndMethod + " 耗时为：" + (endTime-startTime) + "ms");
        return obj;
    }

     void syncReport(RootRealTimeInfo exception,int level){
         log.info("开始上报异常信息 {syncReport}");
        new Thread(new Runnable() {
            @Override
            public void run() {
                Map map = new HashMap();
                InstitutionRegisterInfo ig = new InstitutionRegisterInfo();
                map.put("bt:servName",ig.getParentServerName());
                map.put("bt:gnrlId",ig.getParentGnrlId());
                RealTimeReport r = new RealTimeReport();
                Document document = r.genByNodeLevel(currentNode.getLevel(),ig,exception,map);
//                Assert.isNull(document,"文档对象为空");
                String fileName = fileName(currentNode.getLevel());
                String fullPath = xmlPath+fileName+".xml";
                XmlUtils.writeXml(document,xmlPath,fileName+".xml");
                boolean b = XmlUtils.validateXMLSchema(new File(rootPath+filePath(currentNode.getLevel())),new File(fullPath));
                if (!b){
                    log.error("xml 文件验证失败");
                }
                String localPath = fullPath;
                XmlUtils.signXml(localPath, privateKey);
                String outPath = tarPath+fileName+".tar.gz";
                List<String> filePath = Arrays.asList(localPath, localPath);
                XmlUtils.packetXml(outPath, filePath);

                File file = new File(tarPath+fileName+".tar.gz");
                InputStream inputStream = null;
                try {
                    inputStream = new FileInputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
//                FTPClient ftpClient = new FtpConnect().getFTPClient(outDir);
                SFtpUtil sFtpUtil = new SFtpUtil(sFtpProperties);

                String suffix = "/"+dataType(level)+"/"+new SimpleDateFormat("yyyyMMdd").format(new Date());
                log.info("文件上传路径 =>{}",suffix+"/"+fileName+".tar.gz");
                sFtpUtil.upload(suffix+"/"+fileName+".tar.gz",inputStream);
//                FtpUtil.uploadFile(inputStream,fileName+".tar.gz",ftpClient);
            }
        }).start();
    }

    static String filePath(int level){
        if (Constant.level_root == level)
            return "/root/rootReaTimInfo.xsd";
        if (Constant.level_2 == level)
            return "/regservice/regSrvReaTimInfo.xsd";
        if (Constant.level_3== level)
            return "/enterprise/entReaTimInfo.xsd";
        return "";
    }

    static String fileName(int level){
        String platTYpe = "";
        String grnlId = new InstitutionRegisterInfo().getGnrlId();
        String dataType = "";
        int i = RandomUtil.getRandom().nextInt(10000,99999);
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+i;
        if (Constant.level_root == level)
            platTYpe = "ROOT-";
            dataType = "RRMD02-";
        if (Constant.level_2 == level)
            platTYpe = "ZS-";
            dataType = "SRMD02-";
        if (Constant.level_3== level)
           platTYpe = "ENT-";
           dataType = "ERMD02-";
        return platTYpe+grnlId+dataType+timestamp;
    }

    static String dataType(int level){
        String []arr = {"RRMD02","SMP","SRMD02","ERMD02"};
        return arr[level];
    }

}
